﻿#region Libraries

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.UI;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.WebControls;

#endregion

namespace XYZ_Inventory
{
    public partial class RawMaterialReports : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                XYZDBContext dbContext = new XYZDBContext();
                GetChartType();
                ddlMaterialType.DataSource = dbContext.RawMaterialTypes.ToList();
                ddlMaterialType.DataBind();
                ddlRawMaterial.DataSource =
                    dbContext.RawMaterialInventories.Where(x => x.RawMaterialType == ddlMaterialType.SelectedValue).ToList();
                ddlRawMaterial.DataBind();
                ddlYears.DataTextField = "Year";
                ddlYears.DataValueField = "Year";
                ddlYears.DataSource = dbContext.FinishedProductSales.GroupBy(x => x.DateAndTime.Year).Select(y => new
                {
                    Year = y.Key
                });
                ddlYears.DataBind();
                LoadData();
                LoadRawMaterialSales();
            }
            Chart1.ChartAreas[0].AxisY.Title = "Raw material usage %";
            Chart1.ChartAreas[0].AxisX.Title = "Raw material";
            Chart1.ChartAreas[0].AxisX.Interval = 1;
            Chart1.ChartAreas[0].AxisY.Minimum = 0;
            Chart1.ChartAreas[0].AxisY.Maximum = 100;
            Chart1.ChartAreas[0].AxisY.Interval = 5;

            Chart2.ChartAreas[0].AxisY.Title = "Raw material usage (Units)";
            Chart2.ChartAreas[0].AxisX.Title = "Month";
            Chart2.ChartAreas[0].AxisX.Minimum = 0;
            Chart2.ChartAreas[0].AxisX.Maximum = 12.99;
            Chart2.ChartAreas[0].AxisX.Interval = 1;
            Chart2.ChartAreas[0].AxisY.Minimum = 0;

            Chart3.ChartAreas[0].AxisY.Title = "Raw material Orders (#)";
            Chart3.ChartAreas[0].AxisX.Title = "Month";
            Chart3.ChartAreas[0].AxisX.Minimum = 0;
            Chart3.ChartAreas[0].AxisX.Maximum = 12.99;
            Chart3.ChartAreas[0].AxisX.Interval = 1;
            Chart3.ChartAreas[0].AxisY.Minimum = 0;
            Chart3.ChartAreas[0].AxisY.Interval = 1;
        }

        private void GetChartType()
        {
            foreach (int chartValue in Enum.GetValues(typeof(SeriesChartType)))
            {
                ListItem listItem = new ListItem(Enum.GetName(typeof(SeriesChartType), chartValue),
                    chartValue.ToString());
                ddlReportChart1.Items.Add(listItem);
            }
        }

        private void LoadData()
        {
            Chart1.Series["Series"].ChartType =
                (SeriesChartType)Enum.Parse(typeof(SeriesChartType), "8");

            Series series1 = Chart1.Series["Series"];

            XYZDBContext dbContext = new XYZDBContext();

            // Raw material import results ( Not using currently )
            int month = DateTime.Now.Month;
            List<RawMaterialResults> results =
                dbContext.RawMaterialOrders.Where(x => x.OrderDate.Month.Equals(month)).GroupBy(x => x.RawMaterialID)
                    .Select(
                        y =>
                            new RawMaterialResults
                            {
                                RawMaterialId = y.FirstOrDefault().RawMaterialID,
                                Import = y.Sum(z => z.Quantity)
                            }).ToList();

            // Product production results
            List<FinishedProducts> products =
                dbContext.FinishedProductLogs.Where(x => x.DateAndTime.Month.Equals(month))
                    .GroupBy(y => y.ProductId)
                    .Select(z => new FinishedProducts
                    {
                        ProductId = z.FirstOrDefault().ProductId,
                        Count = z.Sum(a => a.Quantity)
                    }).ToList();

            // Final raw materials
            List<RawMaterialUsage> rawMaterials = dbContext.RawMaterialInventories.Select(x => new RawMaterialUsage
            {
                RawMaterialId = x.RawMaterialID,
                CurrentStock = x.Stock,
                Usage = 0
            }).ToList();

            foreach (FinishedProducts product in products)
            {
                List<RawMaterialForProduct> rawMaterialsOfProduct =
                    dbContext.RawMaterialForProducts.Where(x => x.ProductID == product.ProductId).ToList();

                foreach (RawMaterialForProduct raw in rawMaterialsOfProduct)
                {
                    RawMaterialUsage rawMaterial = rawMaterials.Single(y => y.RawMaterialId == raw.RawMaterialID);
                    rawMaterial.Usage += raw.Quantity * product.Count;
                }
            }

            foreach (RawMaterialUsage r in rawMaterials)
            {
                string materialName =
                    dbContext.RawMaterialInventories.Single(x => x.RawMaterialID == r.RawMaterialId).RawMaterialName;
                if (r.CurrentStock + r.Usage != 0)
                {
                    r.Usage = r.Usage * 100 / (r.CurrentStock + r.Usage);
                }
                else
                {
                    r.Usage = 0;
                }

                series1.Points.AddXY(r.RawMaterialId + " - " + materialName, r.Usage);
            }
        }

        private void LoadRawMaterialSales()
        {
            XYZDBContext dbContext = new XYZDBContext();

            // Raw material usage from sales
            Chart2.Series["Series"].ChartType =
                (SeriesChartType)Enum.Parse(typeof(SeriesChartType), "11");

            Series series2 = Chart2.Series["Series"];
            int Year = Convert.ToInt32(ddlYears.SelectedValue);
            // Product production results
            RawMaterialUsage material = new RawMaterialUsage
            {
                RawMaterialId = Convert.ToInt32(ddlRawMaterial.SelectedValue),
                Usage = 0
            };

            for (int c = 1; c < 13; c++)
            {
                List<FinishedProducts> salesFinishedProducts =
                    dbContext.FinishedProductSales.Where(x => x.DateAndTime.Year.Equals(Year) && x.DateAndTime.Month.Equals(c))
                        .GroupBy(y => y.ProductID)
                        .Select(z => new FinishedProducts
                        {
                            ProductId = z.FirstOrDefault().ProductID,
                            Count = z.Sum(a => a.Quantity)
                        }).ToList();

                foreach (FinishedProducts product in salesFinishedProducts)
                {
                    List<RawMaterialForProduct> rawMaterialsOfProduct =
                        dbContext.RawMaterialForProducts.Where(x => x.ProductID == product.ProductId).ToList();

                    foreach (RawMaterialForProduct raw in rawMaterialsOfProduct)
                    {
                        if (raw.RawMaterialID == material.RawMaterialId)
                            material.Usage += raw.Quantity * product.Count;
                    }
                }
                string monthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(c);
                series2.Points.AddXY(monthName, material.Usage);
            }

            LoadRawMaterialOrders();
        }

        private void LoadRawMaterialOrders()
        {
            XYZDBContext dbContext = new XYZDBContext();

            // Raw material usage from sales
            Chart3.Series["Series"].ChartType =
                (SeriesChartType)Enum.Parse(typeof(SeriesChartType), "11");

            Series series3 = Chart3.Series["Series"];
            int Year = Convert.ToInt32(ddlYears.SelectedValue);
            // Product production results
            RawMaterialUsage material = new RawMaterialUsage
            {
                RawMaterialId = Convert.ToInt32(ddlRawMaterial.SelectedValue),
                NumberOfOrders = 0
            };

            for (int c = 1; c < 13; c++)
            {
                material.NumberOfOrders =
                     dbContext.RawMaterialOrders.Where(x => x.OrderDate.Year.Equals(Year) && x.OrderDate.Month.Equals(c) && x.RawMaterialID == material.RawMaterialId)
                         .GroupBy(x => x.RawMaterialID).Count();
                string monthName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(c);
                series3.Points.AddXY(monthName, material.NumberOfOrders);
            }
        }

        protected void ddlReportChart1_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            LoadData();
        }

        protected void ddlMaterialType_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            XYZDBContext dbContext = new XYZDBContext();
            ddlRawMaterial.DataSource =
                    dbContext.RawMaterialInventories.Where(x => x.RawMaterialType == ddlMaterialType.SelectedValue).ToList();
            ddlRawMaterial.DataBind();
            LoadData();
            LoadRawMaterialSales();
        }

        protected void ddlYears_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            LoadData();
            LoadRawMaterialSales();
        }

        protected void ddlRawMaterial_OnSelectedIndexChanged(object sender, EventArgs e)
        {
            LoadData();
            LoadRawMaterialSales();
        }
    }

    public class RawMaterialResults
    {
        public int RawMaterialId { get; set; }
        public int Import { get; set; }
        public float Usage { get; set; }
    }

    public class FinishedProducts
    {
        public int ProductId { get; set; }
        public int Count { get; set; }
    }

    public class RawMaterialUsage
    {
        public int RawMaterialId { get; set; }
        public int CurrentStock { get; set; }
        public int Usage { get; set; }
        public int NumberOfOrders { get; set; }
    }
}